import os
import pickle

"""
HISTORYPOLICY defines some policy related factors for history maintenance.
MAXNUMBEROFITEMS is very obvious
LENGTH_SORT_FACTOR is a parameter that controls sorting,i.e shorter strings with
length equal to some value t can be assigned more preference than those of
length equal to LENGTH_SORT_FACTOR+t.This may act as the final sorting condition
or act as a trigger to one or more conditions in the sort comparision function
FREQUENCY_SORT_RATIO determines when comparative frequency ratios between two
ratio overpowers the LENGTH_SORT_FACTOR
For example consider,2 commands emerald and emerald --replace with frequencies of
past occurence 4 and 10 respectively.Since the diffrence between their lengths
is greater than 3,i.e our length so whenever the user starts typing eme,we would
like to give him the shorter option emerald first,so that he/she can avoid typing
as much as possible,however we also know from the frequencies that 10/4=2.5>2.4
i.e emerald --replace seems to be the user's favorite.So we are stuck between
choosing a favorite and possibly run the risk of giving the user extra stuff to
type than he wanted or let him type 'emerald' all the way before an autocompletion
hint occurs for emerald --replace.It is these competing temptations that we attempt
to control or favor using the above two parameters.
"""

class HistoryManager:
    """
    This class contains the basic stuff for reading and saving commmand history
    The history file is a simple pickle file that contains
    This history info is in the profile directory(the profile directory is .glassbead
    in the users home folder) in a file called commandhistory which contains a
    python list named HISTORY in pickled or serialized format.
    """
    def __init__(self):
        self.load()
        self.FREQUENCYDIST={}
        self.SORTEDKEYS=[]
        self.readpolicy()

    def readpolicy(self):
        """
        This section reads the command policy and uses it to determine the command selection behaviour
        Available policy options for choosing between history and aliases are
        USE_SHORTEST_OF_BOTH_HISTORY_AND_ALIASES
        PREFER_HISTORY
        PREFER_ALIASES
        """

        self.HISTORY_POLICY={
                'MAXNUMBEROFITEMS':500,
                'LENGTH_SORT_FACTOR':1,
                'FREQUENCY_SORT_RATIO':2.0
              }
        ConfigError=False
        fname = os.path.join("~", ".glassbead", "policies.py")
        fname = os.path.expanduser(fname)
        if os.path.exists(fname):
            try:
                globs={}
                execfile(fname, {}, globs)
            except Exception, v:
                ConfigError=True
        else:
            ConfigError=True

        if not ConfigError:
            if globs.get("HISTORY_POLICY"):
                self.HISTORY_POLICY=globs.get("HISTORY_POLICY")
            print self.HISTORY_POLICY

    def load(self):
        """
        Restores the pickled command history object
        """
        ConfigError=False
        fname = os.path.join("~", ".glassbead", "history")
        fname = os.path.expanduser(fname)
        if os.path.exists(fname):
            try:
                file=open(fname,"r")
                self.HISTORY=pickle.load(file)
            except Exception, v:
                ConfigError=True
                self.HISTORY=[]
        else:
            ConfigError=True
            self.HISTORY=[]
            file=open(fname,"w")
            pickle.dump([],file)

    def save(self):
        ConfigError=False
        fname = os.path.join("~", ".glassbead", "history")
        fname = os.path.expanduser(fname)
        if os.path.exists(fname):
            try:
                file=open(fname,"w")
                pickle.dump(self.HISTORY,file)
            except Exception, v:
                ConfigError=True
        else:
            ConfigError=True
         
    def frequencydist(self):
        for entry in self.HISTORY:
            if self.FREQUENCYDIST.has_key(entry):
                self.FREQUENCYDIST[entry]=self.FREQUENCYDIST[entry]+1
            else:
                self.FREQUENCYDIST[entry]=1
        self.SORTEDKEYS=self.FREQUENCYDIST.keys()
        self.SORTEDKEYS.sort(self.compareentries)
        #self.SORTEDKEYS.sort(lambda x,y:cmp(self.FREQUENCYDIST[y],self.FREQUENCYDIST[x]))
         
    def gethistory(self):
        return self.HISTORY

    def compareentries(self,x,y):
        """
        This method is used when sorting history entries based on frequency,
        command length and other parameters.It provides complex custom sorting
        based onto various parameters like history usage and command length
        """
        yfreq=self.FREQUENCYDIST[y]
        xfreq=self.FREQUENCYDIST[x]
        xlen=len(x)
        ylen=len(y)
        SORT=1
        DONOTSORT=-1
        if yfreq>xfreq:
            #Read the HISTORYPOLICY comments to better understand what's happen
            #ing here
            if ylen<=xlen+self.HISTORY_POLICY['LENGTH_SORT_FACTOR'] :
                return SORT
            else:
                if yfreq/xfreq>=self.HISTORY_POLICY["FREQUENCY_SORT_RATIO"]:
                    return SORT
                else:
                    return DONOTSORT
        else:
            if xlen<=ylen+self.HISTORY_POLICY['LENGTH_SORT_FACTOR'] :
                return DONOTSORT
            else:
                if xfreq/yfreq>=self.HISTORY_POLICY["FREQUENCY_SORT_RATIO"]:
                    return DONOTSORT
                else:
                    return SORT
            
    def appendentry(self,entry):
        self.HISTORY.append(entry)
        if len(self.HISTORY)>self.HISTORY_POLICY['MAXNUMBEROFITEMS']:
            self.HISTORY=[]
            self.save()

    def getclosesthistoryterm(self,str):
        self.frequencydist()
        for i in self.SORTEDKEYS:
            if i.startswith(str):
                return i
        return ""

    def getclosesthistorylist(self,str):
        self.frequencydist()
        list=[]
        for i in self.SORTEDKEYS:
            if i.startswith(str):
                list.append(i)
        return list

if __name__=="__main__":
    mgr=HistoryManager()
    print mgr.gethistory()
    mgr.HISTORY.append('fbrunner')
    mgr.HISTORY.append('eden')
    mgr.HISTORY.append('eden')
    mgr.HISTORY.append('eden')
    mgr.HISTORY.append('eden')
    mgr.HISTORY.append('eden')
    mgr.HISTORY.append('eden')
    mgr.HISTORY.append('eden')
    mgr.HISTORY.append('eden')
    mgr.HISTORY.append('eden')
    mgr.HISTORY.append('ek')
    mgr.HISTORY.append('ek')
    mgr.HISTORY.append('ek')
    mgr.appendentry('ek')
    mgr.save()
    print mgr.getclosesthistoryterm('e')
    print mgr.SORTEDKEYS
    print mgr.getclosesthistoryterm('e')
    print mgr.getclosesthistorylist('')
